#pragma once

#ifndef EVENT_HOLDER
#define EVENT_HOLDER

#include "EventListener.h"

namespace cevent {

class findEventByEvent
{
public:
	static const EventListener* compare_to;
	bool operator()(const EventListener* event) {
		return event->handler->GetSender() == compare_to->handler->GetSender();
	}
};

template<typename T>
class EventHolder : virtual private VirtualLocker // or just use final
{
public:
	EventHolder() {};
	virtual ~EventHolder() {
		unSignUpAll();
	};

	// add new EventListener to the list;
	// override existing EventListener delegate if it reference to the same sender; new event will be pushed to the end of EventsChain in EventController
	// meaning that is only one delegate per sender;
	EventHolder& operator+=(T* e) {
		EventListener* event = static_cast<EventListener*>(e);
		findEventByEvent::compare_to = event;
		std::set<EventListener*>::iterator it = std::find_if(eventListener.begin(), eventListener.end(), findEventByEvent());
		if (it != eventListener.end())
		{
			EventListener* tmp_event = *it;
			eventListener.erase(it);
			DELETE(tmp_event);
			eventListener.insert(event);
		}
		else {
			eventListener.insert(event);
		}
		return *this;
	}
	
	// remove EventListener, that have the same sender;
	EventHolder& operator-=(T* e) {
		EventListener* event = static_cast<EventListener*>(e);
		findEventByEvent::compare_to = event;
		std::set<EventListener*>::iterator it = std::find_if(eventListener.begin(), eventListener.end(), findEventByEvent());
		if (it != eventListener.end())
		{
			EventListener* tmp_event = *it;
			eventListener.erase(it);
			DELETE(tmp_event);
		}
		DELETE(e);
		return *this;
	}

	// remove all EventListeners from eventHolder;
	EventHolder& operator--(int) {
		unSignUpAll();
		return *this;
	}
private:
	EventHolder(const EventHolder&); // undef
	void operator=(const EventHolder&); // undef
	static void* operator new (size_t size); // undef

	void unSignUpAll() {
		for each (EventListener* event in eventListener)
		{
			DELETE(event);
		}
		eventListener.clear();
	}

	std::set<EventListener*> eventListener;
};

}

#endif // EVENT_HOLDER